package com.sikaryofficial.backend.manager.information;

import cn.hutool.core.collection.CollUtil;
import com.sikaryofficial.backend.constant.ArticleContentTypeEnum;
import com.sikaryofficial.backend.constant.ArticleSourceEnum;
import com.sikaryofficial.backend.constant.MyStatisticsTypeEnum;
import com.sikaryofficial.backend.domain.vo.ObjectCount;
import com.sikaryofficial.backend.service.IAttachmentService;
import com.sikaryofficial.backend.service.IMyStatisticsService;
import com.sikaryofficial.backend.service.brandspecial.cache.BrandSpecialCacheService;
import com.sikaryofficial.backend.service.follow.cache.FollowCacheService;
import com.sikaryofficial.backend.service.user.UserCacheService;
import com.sikaryofficial.backend.service.useraction.cache.UserActionCacheService;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.model.att.AttachmentResp;
import com.sikaryofficial.system.api.model.infomation.ArticleDTO;
import com.sikaryofficial.system.api.model.infomation.FollowCountVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author : qinjinyuan
 * @desc :  文章数据同步管理类
 * @date : 2024/03/13 11:50
 */
@Component
@Slf4j
public class ArticleActionDataManager {
    @Autowired
    private UserActionCacheService userActionCacheService;
    @Autowired
    private IMyStatisticsService myStatisticsService;
    @Autowired
    private UserCacheService userCacheService;
    @Autowired
    private IAttachmentService attachmentService;
    @Autowired
    private FollowCacheService followCacheService;
    @Autowired
    private BrandSpecialCacheService brandSpecialCacheService;

    /**
     * 获取文章列表附件
     *
     * @param articleIds
     * @return
     */
    private Map<Long, List<AttachmentResp>> getAttachmentByIds(List<Long> articleIds) {
        return attachmentService.getAttachmentByIds(articleIds);
    }

    private void processOtherInfo(Long userId, ArticleDTO item) {
        if (Objects.isNull(userId)) {
            return;
        }
        // 虚拟作者替换
        Long createdById = item.getCreatedBy();
        if (ArticleSourceEnum.BACKEND.getCode().equals(item.getSource())) {
            brandSpecialCacheService.processVirtualAccount(item);
            createdById = item.getCreatedBy();
        } else {
            // 作者图像
            item.setAvatar(userCacheService.getSignUserAvatar(createdById));
            item.setNickName(userCacheService.getSignUserNickName(createdById));
        }
        // 用户到的关注数量 (粉丝数量)
        FollowCountVO followCountVO = followCacheService.getFollowCount(createdById);
        item.setFansCount(Objects.nonNull(followCountVO.getFansCount()) ? followCountVO.getFansCount() : 0L);
        // 查看当前用户是否关注文章作者
        item.setHasFollow(followCacheService.hasFollow(userId, createdById));
        // contentTypeDesc
        ArticleContentTypeEnum contentTypeEnum = ArticleContentTypeEnum.getNameByCode(item.getContentType());
        item.setContentTypeDesc(Objects.nonNull(contentTypeEnum) ? contentTypeEnum.getName() : "");
    }

    /**
     * 构建评价的点赞统计及个人点赞数据
     *
     * @param result
     */
    public void buildUserActionData(List<ArticleDTO> result, Long userId) {
        if (CollUtil.isEmpty(result)) {
            return;
        }
        try {
            processArticleData(result);
            enhanceArticleDataWithAttachments(result, userId);
        } catch (NullPointerException e) {
            log.error("Null pointer exception occurred. Possibly due to null element in the result list or null context in processing.", e);
        } catch (IllegalArgumentException e) {
            log.error("Illegal argument exception occurred. Check the validity of the input data.", e);
        } catch (Exception e) {
            // 捕获其他未预期的异常
            log.error("Unexpected exception occurred during processing: {}", e.getMessage(), e);
        }
    }

    private void enhanceArticleDataWithAttachments(List<ArticleDTO> result, Long userId) {
        List<Long> articleIds = result.stream()
                .map(ArticleDTO::getArticleId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, List<AttachmentResp>> attachmentMap = getAttachmentByIds(articleIds);
        result.stream().filter(Objects::nonNull).forEach(actionItem -> safeProcessArticleInfo(actionItem, userId, attachmentMap));
    }

    private void safeProcessArticleInfo(ArticleDTO actionItem, Long userId, Map<Long, List<AttachmentResp>> attachmentMap) {
        try {
            // 是否自己点赞
            checkUserActionsByUserId(actionItem);
            // 其他信息处理
            processOtherInfo(userId, actionItem);
            // 填充附件
            List<AttachmentResp> attachmentList = attachmentMap.get(actionItem.getArticleId());
            actionItem.setAttachmentList(attachmentList);
            if (CollUtil.isNotEmpty(attachmentList)) {
                actionItem.setCoverUrlList(attachmentList.stream().filter(attachmentResp -> attachmentResp.getHasCover() == 1).collect(Collectors.toList()));
            }
        } catch (NullPointerException e) {
            log.error("Null pointer exception while processing article info. Article ID: {}", actionItem.getArticleId(), e);
        } catch (Exception e) {
            log.error("Unexpected exception while processing article info. Article ID: {}", actionItem.getArticleId(), e);
        }
    }

    public void processArticleData(List<ArticleDTO> result) {
        // 点赞数量填充
        List<ObjectCount> objectCountList = myStatisticsService.countByObjectIds(result.stream().map(ArticleDTO::getArticleId).collect(Collectors.toList()));
        Map<Long, List<ObjectCount>> objectCountMap = objectCountList.stream().collect(Collectors.groupingBy(ObjectCount::getObjectId));
        result.forEach(replyDTO -> processCountData(replyDTO, objectCountMap));
    }

    private void processCountData(ArticleDTO replyDTO, Map<Long, List<ObjectCount>> objectCountMap) {
        List<ObjectCount> objectCounts = MapUtils.getObject(objectCountMap, replyDTO.getArticleId());
        if (CollUtil.isNotEmpty(objectCounts)) {
            populateLikesCount(replyDTO, objectCounts);
            populateCommentsCount(replyDTO, objectCounts);
            populateCollectionCount(replyDTO, objectCounts);
            populateForwardCount(replyDTO, objectCounts);
        }
    }

    /**
     * 点赞
     *
     * @param replyDTO
     * @param objectCounts
     */
    private void populateLikesCount(ArticleDTO replyDTO, List<ObjectCount> objectCounts) {
        objectCounts.stream()
                .filter(e -> MyStatisticsTypeEnum.LIKES_ARTICLE.getBusinessType().equals(e.getBusinessType()))
                .findFirst()
                .ifPresent(e -> replyDTO.setLikesCount(e.getObjectCount()));
    }

    /**
     * 评论
     *
     * @param replyDTO
     * @param objectCounts
     */
    private void populateCommentsCount(ArticleDTO replyDTO, List<ObjectCount> objectCounts) {
        objectCounts.stream()
                .filter(e -> MyStatisticsTypeEnum.COMMENTS_ARTICLE_COUNT.getBusinessType().equals(e.getBusinessType()))
                .findFirst()
                .ifPresent(e -> replyDTO.setEvaluationCount(e.getObjectCount()));
    }

    /**
     * 收藏
     *
     * @param replyDTO
     * @param objectCounts
     */
    private void populateCollectionCount(ArticleDTO replyDTO, List<ObjectCount> objectCounts) {
        objectCounts.stream()
                .filter(e -> MyStatisticsTypeEnum.COLLECTION_ARTICLE.getBusinessType().equals(e.getBusinessType()))
                .findFirst()
                .ifPresent(e -> replyDTO.setCollectionCount(e.getObjectCount()));
    }

    private void populateForwardCount(ArticleDTO replyDTO, List<ObjectCount> objectCounts) {
        objectCounts.stream()
                .filter(e -> MyStatisticsTypeEnum.FORWARD_ARTICLE.getBusinessType().equals(e.getBusinessType()))
                .findFirst()
                .ifPresent(e -> replyDTO.setForwardCount(e.getObjectCount()));
    }

    private void checkUserActionsByUserId(ArticleDTO item) {
        Long userId = SecurityUtils.getUserId();
        if (item.getLikesCount() > 0) {
            item.setHasOwnerLikes(userActionCacheService.getOwnerAction(userId, item.getArticleId(),
                    MyStatisticsTypeEnum.LIKES_ARTICLE.getBusinessType()));
        }
        if (item.getCollectionCount() > 0) {
            item.setHasOwnerCollection(userActionCacheService.getOwnerAction(userId, item.getArticleId(),
                    MyStatisticsTypeEnum.COLLECTION_ARTICLE.getBusinessType()));
        }
    }
}
